import { UploadOutlined , DownloadOutlined} from '@ant-design/icons';
import { ReactSortable } from "react-sortablejs";
import myMessage from "../../../common/utils/message"
import React, { useEffect, useRef, useState } from "react";
import clsx from 'clsx';
import { Checkbox, Modal, Upload, Button, Tooltip, message, Spin} from "antd";
import { useFormField } from "../../context/form-context";
import { useForm } from "../../context/metadata-context";
import cloneDeep from "lodash/cloneDeep";
import _extend from "lodash/extend";
import uniqBy from "lodash/uniqBy"//去重
import moment from "moment";
import "./index.css";
import { useSelections, useUpdate } from "ahooks";
import request from "../../utils/request";
import { openWin, isIE, buildUrl, formatNumber } from "../../utils";
import ntkoBrowser from "../../../../ntko/ntkobackground.min.js"
import { useInject } from '../../context/inject-context';
import { setFile_sort, checkInFile, updateFile, fileDownload, setDelete_attachments, setValue, deleteFile } from './fileUtilis'; 
import eventBus, { useSubscribe } from '../../eventBus';
import FileItem from './FileItem';
import UploadButton from "./UploadButton"

let defaultConfig = {
  //这一批属性来源 tplData.form.data_control （步骤权限）
  // "code": "a8",
  // "name": "附件上传-多文件",
  // "type": "file",
  // "is_show": true,
  // "is_upload": true,
  // "is_required": false,

  //这一批属性来源 tplData.form.form_meta_data （表单设计器）
  // "designProps": {
  //   "code": "a8",
  //   "name": "附件上传-多文件",
  //   "ui": "wfd_file",
  //   "title": "附件上传-多文件",
  //   "layout": "control_layout_leftRight",
  //   "defaultValue": "",
  //   "groupTitle": "",
  //   "byTableGroupTitle": false,
  //   "title_w": 85
  // },
  // "isUsed": false,

  //这一批属性来源 tplData.form.data_define （业务对象）
  // "show_type": "",
  // "show_type_name": "",
  // "props": {
  //     "is_support_multiple_file": true
  // },
  // "type_name": "文件",

  //来源 tplData.form.defaultValueConf
  // "default": null
}

export default function ({ id, field, label, rules, showLabel = false, onChange, onBlur, displayFormatter, valueFormatter, required, cell, rowIndex, ...others }) {
  
  const injectInfo = useInject();//分组信息
  const groupContext = useInject();
  
  let fileInfoRef = useRef({
    __isTypeFile__: false, //当前附件字段是否包含分类
    __isAllDownload__: true, //显示全部下载
    __init__: false,//记录组件是否初始化过，默认为false，初始化后设置为true
    __fileType__: { "": { name: "", data: [] } }//默认附件分类
  });
  let fileListCurrent = fileInfoRef.current;

  let errorMessageTextRef = useRef("");//附件签出信息
  rules = [
    {
      message: ()=>{
        return ()=>{
          return errorMessageTextRef.current
        }
      },
      validator(rule, value, callback) {
        var ok = true;
        Object.keys(fileListCurrent.__fileType__).find(function(fileTypeKey){//1.遍历所有分类
          let fileInfo = fileListCurrent.__fileType__[fileTypeKey];
          if(fileInfo?.data){
            return fileInfo.data.find(function(file){
              if(file.LockedUser && file.LockedUser !== ""){
                errorMessageTextRef.current = "“" +  file.name + "”已签出，请先签入文件！"
                ok = false;
                return true;
              }
            });
          }
        })
        return ok;
      }
    }
    // ,
    // {
    //   priority: 1,//提示优先级上升
    //   message: ()=>{
    //     return ()=>{
    //       return errorMessageTextRef.current
    //     }
    //   },
    //   validator(rule, value, callback) {
    //     if (injectInfo?.isDefaultRequired === true) {
    //       if(value === "" || value === null || value === undefined){
    //         errorMessageTextRef.current = "附件要求必传，请上传附件！"
    //         return false;
    //       }
    //     }
    //     return true;
    //   }
    // }//校验必填
  ];//自定义校验

  const { input: fieldConfig, property, validation, readonly, className, isDisplay } = useFormField({
    field,
    rules,
    onChange,
    displayFormatter,
    valueFormatter,
    triggerBlurAsChange: true
  });
  const form =useForm().root;
  const { data: tplData, urlPrefix, params, csrfToken, mode } = form;
  const updater = useUpdate();

  // tplData.form.form_data.attachmentTypes = {
  //   "2cc68f93-57e6-4de1-8840-d3602fe2adee":{
  //     "id":"62d7a3d2c948b5983375225490028700",
  //     "guid":"2cc68f93-57e6-4de1-8840-d3602fe2adee",
  //     "name":"附件分类一",
  //     "is_required":0,
  //     "data":[]
  //   },
  //   "d93b1802-4083-455b-95bd-9512c3168e2a":{
  //     "id":"62d7a3d2c94a39065643692011010811",
  //     "guid":"d93b1802-4083-455b-95bd-9512c3168e2a",
  //     "name":"其他附件分类",
  //     "is_required":0,
  //     "data":[]
  //   }
  // }; // 测试用的附件分类信息

  const fileIdList = useRef([]); //缓存全选附件id
  useEffect(function(){
    //附件数据清洗
    function setFileInfo() {
      const fieldCode = cell.code; //当前字段code
      const attachments = tplData.form.form_data.attachments; //当前流程所有附件 只包含完整附件基础信息（附件名称、签出信息、上传事件等等），不包含附件权限！
      const file_control = tplData.form.file_control; //当前流程所有附件 只包含附件步骤权限信息(上传、签入、签出、删除等权限)
      const attachmentTypes = tplData.form.form_data.attachmentTypes; //附件分类
      
      var fileTypeInfo = fileListCurrent.__fileType__; // 附件分类
      if (attachmentTypes != null) {//如果存在附件分类，再用实际的分类数据覆盖
        if(fileListCurrent.__init__ === false){//组件初始化时，用后端给的分类进行覆盖
          fileTypeInfo = cloneDeep(attachmentTypes); //复制一份附件分类，每个字段都拥有一样的附件分类
        }
        fileListCurrent.__isTypeFile__ = true; //标记当前附件包含附件分类
      }else{
        fileListCurrent.__isTypeFile__ = false; //标记当前附件不包含附件分类
      }

      if(fileListCurrent.__init__ !== false){//同步业务数据后更新

        if(attachmentTypes) {//如果后端返回了最新的附件分类，把后端给的分类直接覆盖
          fileTypeInfo = cloneDeep(attachmentTypes); //复制一份附件分类，每个字段都拥有一样的附件分类
        }else{//没有分类，重置为空分类
          fileTypeInfo = { "": { name: "", data: [] } };
        }
        // //1.删除分类 && 删除附件
        // //同步前的附件分类 在 最新附件分类不存在时，需要删除
        // //attachmentTypes 后端给的最新附件分类
        // //fileTypeInfo 同步前的附件分类
        // Object.keys(fileTypeInfo).forEach(function(typeKey){
        //   //1.1 删除所有分类下的附件，后面再遍历附件重新追加
        //   let fileType = fileTypeInfo[typeKey];
        //   fileType?.data?.forEach?.(function(file){
        //     deleteFile({
        //       fileId: file.id,
        //       typeKey: typeKey,
        //       fileListCurrent: fileListCurrent,
        //       params: params,
        //       showConfirm: false
        //     });//移除记录
        //   })

        //   //1.2 删除分类
        //   if(attachmentTypes && attachmentTypes[typeKey] === undefined){//组件已有分类在后端给的最新分类内不存在，则记录需要删除的分类
        //     delete fileListCurrent.__fileType__[typeKey];
        //   }
        // });

        // //2.新增分类
        // attachmentTypes && Object.keys(attachmentTypes).forEach(function(typeKey){
        //   if(fileTypeInfo[typeKey] === undefined){//后端给的最新分类，组件已有分类不存在，则需要新增分类
        //     fileTypeInfo[typeKey] = attachmentTypes[typeKey];
        //   }
        // });
      }

      let arr = [];
      //给当前字段添加附件信息
      let inputKeys = [];
      if(typeof fieldConfig.value === "string" && fieldConfig.value.trim() !== ""){
        inputKeys = fieldConfig.value.split(",");//当前字段存储的附件id
      }

      let uniqFile_control = uniqBy(file_control, "id");//对file_control进行去重
      if(uniqFile_control.length != file_control.length){
        console.log("tplData.form.file_control 存在相同的附件，前端做了兼容处理，实际存在脏数据，后端最好修复一下数据");
      }
      //遍历当前流程所有附件，并给当前字段的分类进行追加
      Object.keys(attachments).forEach(function (fileId) {
        let file = attachments[fileId]
        if (inputKeys.indexOf(fileId) > -1) {//2.这个附件在当前字段的值内是存在的
          //如果附件的code属性 == 字段code，并且当前附件在附件信息内存在，则给当前字段存一个附件信息
          let fileControl = uniqFile_control.find(function(fileItem){
            return fileItem.id === fileId;
          });//根据当前附件id查找到附件的步骤权限信息

          let mergeFile = cloneDeep(_extend({}, fileControl, file));//3.把附件基础信息，覆盖到带附件权限的数据上

          //草稿、重新发起、发起，强制禁用 签出编辑 编辑 签出，这里应该后端控制权限，但是后端控制不了
          if(["restart", "start", "draft"].indexOf(tplData.__flowStatus__) > -1){
            mergeFile.is_checkin = false;
            mergeFile.is_checkout_and_edit = false;
            mergeFile.is_edit = false;
          }

          //标签测试数据
          // mergeFile.tags='[{
          //   name:"标签",
          //   style:'{color:'red'};'
          // },{
          //   name:"标签2",
          //   style:'{color:'green'};'
          // }]'

          fileIdList.current.push(file.id); //4.缓存当前字段的所有附件id，用来做全选/反选用

          arr.push(mergeFile);//5.把清洗后的附件信息，追加到当前字段
        }
      });
      
      // 按order_code排序
      arr.sort(function (a, b) {
        return a.order_code - b.order_code;
      });//对附件进行排序

      //把得到的附件信息，放到当前字段对应分类的data内
      arr.forEach(function(file){
        let typeId = file?.attachment_type_guid || "";//当前附件的分类id
        if(fileTypeInfo[typeId]){

          //判断当前附件，在ref缓存内是否已经存在
          let hasFile = fileTypeInfo[typeId].data.find(function(item){
            return item.id === file.id
          });

          //ref不存在时，才进行添加操作
          if(!hasFile){
            fileTypeInfo[typeId].data.push(file);
          }
        }else{
          console.log("看到这个提示，说明附件数据异常了");
          console.log("附件信息", file);
          console.log("附件分类名称：" + file?.attachment_type_name + " 附件分类id：" + typeId + "，但是tplData.form.form_data.attachmentTypes没有对应的分类信息")
          console.log("=============");
        }
      });

      fileListCurrent.__fileType__ = fileTypeInfo;//清洗完，更新current

      //判断是否显示“全选、批量下载”
      if(tplData.isfrontenddownload == 1 || mode === "Print"){// isfrontenddownload = 1
        fileListCurrent.__isAllDownload__ = false;//不显示全部下载
      }else{
        Object.keys(fileListCurrent.__fileType__).find(function(fileTypeKey){//1.遍历所有分类
          let fileInfo = fileListCurrent.__fileType__[fileTypeKey];
          if(fileInfo?.data){
            return fileInfo.data.find(function(file){
              if(file.is_download == false){//存在不可下载的附件
                fileListCurrent.__isAllDownload__ = false;//不显示全部下载
                return true;
              };
            });
          }
        })
      }
      //云空间绝对路径下载， = 1 时禁用批量下载
      if (tplData.attachment_is_open_url == 1) {
        fileListCurrent.__isAllDownload__ = false;
      }
    }
    setFileInfo(); //初始化附件列表数据
    fileListCurrent.__init__ = true;

    setFile_sort({
      params: params,
      cell: cell,
      fileListCurrent: fileListCurrent
    });//设置附件排序

    form.forceUpdate = {};

    updater();//只更新列表数据，不更新tpldata


  }, [tplData.form.form_data.attachments]);
  
  const { selected, allSelected, isSelected, toggle, toggleAll, partiallySelected } = useSelections(fileIdList.current); //全选hook

  //批量下载
  function handleDownloadAll() {
    if (selected.length > 0) {
      fileDownload({
        id: selected,
        params: params,
        tplData: tplData,
        urlPrefix: urlPrefix
      });
    } else {
      myMessage.info({
        content: "请选择要下载的文件！"
      });
    }
  }

  //添加附件
  function addFile({typeKey, updateInfo}){
    let fileList = fileListCurrent.__fileType__[typeKey];
    if(cell.props.is_support_multiple_file !== true){//当前字段是单个文件模式
        fileList.data.forEach(function(item){
          setDelete_attachments({
            fileId: item.id,
            params: params
          });//把当前字段的id都记录到删除记录
        });
        fileList.data= [];//清空当前字段附件信息   data:2 
    }                 
    fileList.data.push(updateInfo);//追加新附件
  }

  //失败提示
  function failTip(erro){
    if(!erro){//兼容什么都没给的情况
      erro = "";
    }
    if(erro.indexOf("未知错误")>-1 || erro === ""){
      erro = "附件上传失败！";
    }
    let titleMsg = null;
    
    if(erro.indexOf("||")>-1){
        let errSplit = erro.split("||");
        titleMsg = errSplit[0]
        erro = errSplit[1];
    }
    myMessage.info({
      title: titleMsg, 
      content: erro
    });
  }

  //渲染附件列表
  function RenderFileList() {
    let showDownAll = false;//隐藏全部下载
    let fileListContent = Object.keys(fileListCurrent.__fileType__).map(function (fileTypeKey, fileTypeIndex) {
      let fileInfo = fileListCurrent.__fileType__[fileTypeKey];
      if(fileInfo.data.length > 0){
        showDownAll = true;//只要有分类存在附件，则显示全部下载
      }
      //完整的附件列表dom
      return (
        <div 
          className={
                      clsx( 
                        mode !== "Print" && "pb-10px pl-6px pr-6px", //打印模式不需要这些class
                        className
                      )
                    } 
          key={fileTypeKey}
        >
          <div className="text-left text-color-666 mb-2px" data-des="附件分类名称">
            {
              //isDisplay=true表单只读 || cell.is_upload !== true 当前附件字段没上传权限
              (form.isDisplay || cell.is_upload !== true)
              ? fileInfo?.name //只读模式显示分类名
              : <UploadButton
                  multiple={cell?.props?.is_support_multiple_file || false}//多选
                  groupId={groupContext?.group?.id}
                  key={cell.code + '-' + fileTypeKey}
                  cell={cell}
                  fileTypeKey={fileTypeKey}
                  fileInfo={fileInfo}
                  tplData={tplData}
                  urlPrefix={urlPrefix}
                  csrfToken={csrfToken}
                  isTypeFile={fileListCurrent.__isTypeFile__}
                  params={params}
                >
                </UploadButton>//编辑模式显示上传按钮
            }
          </div>
          
          {/* 附件列表 */}
          <ReactSortable
            disabled={isDisplay}
            handle={".op-drag"}
            group={injectInfo.group.id + cell.code}
            animation={200}
            // delayOnTouchStart={true}
            list={fileInfo.data}
            setList={function(list){
              
              if(fileListCurrent.__init__){//如果已经初始化过，才执行，解决setList初始化会执行的bug
                list.forEach(function(item){
                  item.attachment_type_guid = fileTypeKey;//附件分类key
                  item.attachment_type_name = fileInfo.name;//附件分类名称
                });//排序后，更新附件的分类信息为当前分类
                fileInfo.data = list;
                setValue({
                  params: params,
                  cell: cell,
                  fileListCurrent: fileListCurrent,
                  fileIdList: fileIdList,
                  fieldConfig: fieldConfig,
                  updater: updater
                });//更新字段信息
              }

            }}
          >
            { 
              fileInfo.data.map(function (file, fileIndex) {
                return <Spin spinning={file.__fileLoading__ === true} key={file.id} size="small" >
                        <FileItem
                          file={file}
                          fileListCurrent={fileListCurrent}
                          isSelected={isSelected}
                          toggle={toggle}
                          isDisplay={isDisplay}
                          cell={cell}
                          fileTypeKey={fileTypeKey}
                          updater={updater}
                          params={params}
                          form={form}
                          csrfToken={csrfToken}
                          tplData={tplData}
                          urlPrefix={urlPrefix}
                          fileIdList={fileIdList}
                          fieldConfig={fieldConfig}
                          mode={mode}
                        ></FileItem>
                      </Spin>
              })
            }
          </ReactSortable>
          {
            fileInfo?.data?.length <= 0
            && <div className="file-no-data pr-10px">暂无数据</div>
          }
        </div>
      );
    });

    return (
      <div className="overflow-hidden text-left file">
        {
          (
            fileListCurrent.__isAllDownload__ //根据权限判断的是否显示全部下载
            && showDownAll //根据附件数量判断是否全部下载，存在附件才显示
          )
         && (
          <div className="mb-1 overflow-hidden drag-title text-color-666 h-30px min-h-30px leading-30px pr-10px pl-10px">

            <div className="float-left input-block mr-10px">
              <Checkbox name="全选" checked={allSelected} onClick={toggleAll} indeterminate={partiallySelected}></Checkbox>
            </div>

            <div className="float-left cursor-pointer title-up text-color-666" id="fileUps" onClick={handleDownloadAll}>
              <DownloadOutlined className='mr-1 text-base' />
              <span>下载</span>
            </div>
          </div>
        )}
        {fileListContent}
      </div>
    );
  }

  //附件上传事件
  function _uploadChange({file, typeKey, result, status}){
    if(status === "uploading"){//上传中
      let uploadLoadingFile = fileListCurrent.__fileType__[typeKey].data.find(function(item){
        if(item.id === file.id){
          return true;
        }
      })
      if(uploadLoadingFile){//附件已经被追加到列表过
        uploadLoadingFile.percent = file.percent;//更改进度
      }else{//没追加过
        addFile({
          typeKey: typeKey,
          updateInfo:{
            ...{
              code: cell.code,
              id: file.id,
              name: file.name,
              attachment_type_guid: typeKey,
              attachment_type_name: fileListCurrent.__fileType__[typeKey].name,
              order_code: fileListCurrent.__fileType__[typeKey].data.length + 1,//排序信息
              show_uploading: true,
              uploadTime: moment(new Date()).format("yyyy-MM-DD hh:mm"),
              percent: file.percent,
              records: {
                upload_user: tplData.CurUserName,
                upload_user_code: tplData.CurUserCode
              }
            }
          }
        })//追加一个附件记录
      }
      updater();//只更新列表数据，不更新tpldata
    }else if(status === "done"){//上传完成
      let response = result;
      let responseData = result?.data || {};
      if(response?.code === 1 && responseData.doc_guid){//上传成功
        updateFile({
          updater: updater,
          fileListCurrent: fileListCurrent,
          fileId: file.id,
          typeKey: typeKey,
          updateInfo:{
            id: responseData.doc_guid,
            is_delete: true,//删除
            is_download: file.size >= 52428800 ? false: true,//下载
            is_edit: false,
            show_uploading: false,//隐藏loading
            is_new: true,
            source: '流程中心',
            is_checkout_and_edit: ["start", "draft", "restart"].indexOf(tplData.__flowStatus__) > -1 ? false : true,//签出并编辑，草稿|发起|重新发起，新上传的附件不显示签出&编辑
            records: {
                upload_user: tplData.CurUserName,
                upload_user_code: tplData.CurUserCode
            }
          }
        });//把新的附件更新到数据内
      }else{//上传失败
        let erro = response?.message;
        if(!erro || responseData.doc_guid === undefined) {//没有返回值 || 返回值没包含docguid
          erro = "上传失败"
          console.log("这里实际是上传挂掉了，后端没返回提示信息，或者没有返回上传成功后的附件id，需要后端排查。")
        }
        failTip(erro);
        deleteFile({
          fileId: file.id,
          typeKey: typeKey,
          params: params,
          cell: cell,
          fileListCurrent: fileListCurrent,
          fileIdList: fileIdList,
          fieldConfig: fieldConfig,
          updater: updater
        });//移除附件
      }
      setValue({
        params: params,
        cell: cell,
        fileListCurrent: fileListCurrent,
        fileIdList: fileIdList,
        fieldConfig: fieldConfig,
        updater: updater
      });//更新字段信息
    }else if(status === "error"){//请求失败
      let response = result || {};
      if(response.code == -601){
          // 获取后缀名
          var index1 = file.name.lastIndexOf(".");
          var index2 = file.name.length;
          var suffix = file.name.substring(index1+1, index2);//后缀名
          myMessage.info({
            content: "不允许上传" + suffix + "类型的文档!<br>只能上传doc,xls,mpp,ppt,vsd,txt,rar,zip,jpg,bmp,gif,docx,xlsx,pptx,xml,png,wmv,asf,avi,flv,tmp,jpeg,cad,rpt,dwg,pdf,mov,mp4,mp3,mpg类型的文件"
          });
      } else {
        myMessage.info({
          content: "附件上传出错，请重新上传！"
        });
      } 
      deleteFile({
        fileId: file.id,
        typeKey: typeKey,
        params: params,
        cell: cell,
        fileListCurrent: fileListCurrent,
        fileIdList: fileIdList,
        fieldConfig: fieldConfig,
        updater: updater
      });//移除附件
      updater();//只更新列表数据，不更新tpldata
    }
  }
  useSubscribe("FileUpload.uploadChange" + cell.code + ".update", function(data){
    _uploadChange(data)
  }, [])


  //编辑模式
  function RenderEditFileList() {
    return <>
              {RenderFileList()}
            </>;
  }

  return isDisplay ? RenderFileList() : RenderEditFileList();
}